Heres my explanation of the code:

10 DIM A$(20),B$(1),RN$(20),RN(2,2),IN$(100),IN(3,2),IL(3),EX(2,4):EX(1,1)=2:EX(2,2)=1:L=1:H=3

DIMs:
A$ is the users command
B$ is the first character of A$. To save line space vs. using A$(1,1) all the time.
RN$ contains all the room names. By all I mean both but it could easily be more.
RN (two-dimensional array) contains info about the start (roomnumber, 1) and end (roomnumber, 2) of room names in RN$
IN$ contains the items names of all items
IN (two-dimensional array) contains info about the start (itemnumber, 1) and end (itemumber, 2) of item names in IN$
IL (array) contains locations (room numbers) for each item. 0 means in your inventory.
EX (two-dimensional array) is info about room exits. (roomnumber, direction) Direction is 1 for north, 2 for south, and you could certainly keep going for a more complicated game and do 3 for east, 4 west, 5 up, and so on. So EX(1,1)=2 means from room number 1, the north exit leads to room 2.

:EX(1,1)=2:EX(2,2)=1
Set up the two exits.

:L=1
Starting location room number.

:H=3
Held items: number of items in inventory is 3.

20 RN$=South BankNorth Bank:RN(1,0)=1:RN(1,1)=10:RN(2,0)=11:RN(2,1)=20:IN$=WOLFGOATCABBAGE:IN(1,1)=1

Set up room and item names. I wanted to keep this flexible so it would be easy to create other environments.

25 IN(1,2)=4:IN(2,1)=5:IN(2,2)=8:IN(3,1)=9:IN(3,1)=9:IN(3,2)=15

More setup of item names. This is part of the main loop  I didnt love that but needed to put it here for space
and it doesnt hurt anything.

:D=0:? :? RN$(RN(L,0),RN(L,1)):? You see::Y=L:EXEC LL

D will tell us if were moving (N or S only for this game) or 0 for non-moving commands.

Print room name, show whats in the room via subroutine.

50 INPUT >,A$:IF A$=:GOTO 25:ENDIF :B$=A$(1,1):IF B$=N:D=1:ELSE :IF B$=S:D=2:ENDIF :ENDIF

Get user command. Check for no input (that would break the A$(1,1)).

North is direction 1, South is direction 2. D stays 0 for other commands.

70 IF D:IF EX(L,D):IF H>1:? Boat too full.:ELSE :L=EX(L,D):ENDIF :ELSE :? YOU CANT GO THAT WAY.:ENDIF :ENDIF

Were trying to move! Dont allow it if inventory is >1 item. Change to new room number if its a real place. If
its 0, theres no exit that way, complain.

80 IF B$=I:? Youre carrying::Y=0:EXEC LL:ENDIF :I=0:IF H=3 AND L=2:? All safe on North Shore, you win!:END :ENDIF

Player typed INVENTORY (or INV or I or IGUANA): list items with location 0 via subroutine. It also checks for end of game conditions
(holding all 3 items in room 2) when you do inventory.

90 IF B$=G OR B$=D:IF INSTR(A$,WOLF):I=1:ENDIF :IF INSTR(A$,GOAT):I=2:ENDIF :IF INSTR(A$,CABBAGE):I=3:ENDIF

Player wants to Get or Drop an item. I wish I had had room to allow Take also. Ham-fistedly assign I as item number based
on object name.

95 IF B$=G:IF IL(I)=L:IL(I)=0:? Got it:H=H+1:ELSE :? NOT HERE:ENDIF

If were Getting (not Taking) make sure its in this room, print message, increment H, or complain.

:ELSE :IF IL(I)=0:IL(I)=L:? Dropped:H=H-1:ENDIF :ENDIF

If were Dropping, make sure its in inventory, print message, decrement H. (Oops, no complaint option.)

96 ENDIF :IF IL(2)=L:IF IL(1)=L:? Wolf gobbles goat!:END :

Dont put these guys down together. (Apparently carrying them both around in your arms in perfectly safe though.)
Note: IF IL(2)=L   the goat is the root cause of all our problems.

ELSE :IF IL(3)=L:? Goat eats cabbage!:END :ENDIF :ENDIF :ENDIF :GOTO 25

Goats loooove some cabbages, apparently. Loop back for next move.

99 PROC LL:Z=0:FOR X=1 TO 3:IF IL(X)=Y:? IN$(IN(X,1),IN(X,2)):Z=1:ENDIF :NEXT X:IF Z=0:? Nothing.:ENDIF :ENDPROC

This subroutine lists the stuff in your inventory (if Y was pre-set to 0) or in the room (if Y was pre-set to L.)